package com.kexio.dynamic.feature.service.impl;

import com.kexio.dynamic.feature.annotation.FeatureToggle;
import com.kexio.dynamic.feature.service.FeatureToggleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 功能开关服务默认实现
 * 
 * @author Kexio
 * @since 1.0.0
 */
@Service
public class DefaultFeatureToggleService implements FeatureToggleService {

    private static final Logger log = LoggerFactory.getLogger(DefaultFeatureToggleService.class);

    // 全局功能开关状态
    private final Map<String, Boolean> globalFeatures = new ConcurrentHashMap<>();
    
    // 用户级功能开关状态
    private final Map<String, Map<Long, Boolean>> userFeatures = new ConcurrentHashMap<>();
    
    // 租户级功能开关状态
    private final Map<String, Map<Long, Boolean>> tenantFeatures = new ConcurrentHashMap<>();
    
    // 功能开关百分比设置
    private final Map<String, Integer> featurePercentages = new ConcurrentHashMap<>();
    
    // 功能开关白名单
    private final Map<String, Set<Long>> featureWhitelists = new ConcurrentHashMap<>();
    
    // 统计信息
    private final AtomicLong totalChecks = new AtomicLong(0);
    private final AtomicLong cacheHits = new AtomicLong(0);
    private final AtomicLong cacheMisses = new AtomicLong(0);
    private final Map<String, AtomicLong> featureUsageStats = new ConcurrentHashMap<>();

    @Override
    public boolean isEnabled(String featureName) {
        if (!StringUtils.hasText(featureName)) {
            return false;
        }
        
        totalChecks.incrementAndGet();
        updateFeatureUsage(featureName);
        
        // 检查全局开关
        Boolean globalState = globalFeatures.get(featureName);
        if (globalState != null) {
            cacheHits.incrementAndGet();
            log.debug("功能开关检查: {} = {}", featureName, globalState);
            return globalState;
        }
        
        cacheMisses.incrementAndGet();
        log.debug("功能开关不存在: {}，默认禁用", featureName);
        return false;
    }

    @Override
    public boolean isEnabled(String featureName, Long userId) {
        if (!StringUtils.hasText(featureName) || userId == null) {
            return isEnabled(featureName);
        }
        
        totalChecks.incrementAndGet();
        updateFeatureUsage(featureName);
        
        // 优先检查用户级开关
        Map<Long, Boolean> userStates = userFeatures.get(featureName);
        if (userStates != null && userStates.containsKey(userId)) {
            Boolean userState = userStates.get(userId);
            cacheHits.incrementAndGet();
            log.debug("用户功能开关检查: {} for user {} = {}", featureName, userId, userState);
            return userState;
        }
        
        // 检查白名单
        if (isUserInWhitelist(featureName, userId)) {
            cacheHits.incrementAndGet();
            log.debug("用户在白名单中: {} for user {}", featureName, userId);
            return true;
        }
        
        // 检查百分比策略
        Integer percentage = featurePercentages.get(featureName);
        if (percentage != null && percentage > 0) {
            boolean enabled = checkPercentageStrategy(featureName, userId, percentage);
            log.debug("百分比策略检查: {} for user {} = {} ({}%)", featureName, userId, enabled, percentage);
            return enabled;
        }
        
        // 回退到全局开关
        return isEnabled(featureName);
    }

    @Override
    public boolean isEnabledForTenant(String featureName, Long tenantId) {
        if (!StringUtils.hasText(featureName) || tenantId == null) {
            return isEnabled(featureName);
        }
        
        totalChecks.incrementAndGet();
        updateFeatureUsage(featureName);
        
        // 检查租户级开关
        Map<Long, Boolean> tenantStates = tenantFeatures.get(featureName);
        if (tenantStates != null && tenantStates.containsKey(tenantId)) {
            Boolean tenantState = tenantStates.get(tenantId);
            cacheHits.incrementAndGet();
            log.debug("租户功能开关检查: {} for tenant {} = {}", featureName, tenantId, tenantState);
            return tenantState;
        }
        
        // 回退到全局开关
        return isEnabled(featureName);
    }

    @Override
    public boolean isEnabled(String featureName, Map<String, Object> context) {
        if (!StringUtils.hasText(featureName)) {
            return false;
        }
        
        if (context == null || context.isEmpty()) {
            return isEnabled(featureName);
        }
        
        // 从上下文中获取用户ID和租户ID
        Long userId = extractUserId(context);
        Long tenantId = extractTenantId(context);
        
        if (userId != null) {
            return isEnabled(featureName, userId);
        }
        
        if (tenantId != null) {
            return isEnabledForTenant(featureName, tenantId);
        }
        
        return isEnabled(featureName);
    }

    @Override
    public void enableFeature(String featureName) {
        if (StringUtils.hasText(featureName)) {
            globalFeatures.put(featureName, true);
            log.info("功能已启用: {}", featureName);
        }
    }

    @Override
    public void disableFeature(String featureName) {
        if (StringUtils.hasText(featureName)) {
            globalFeatures.put(featureName, false);
            log.info("功能已禁用: {}", featureName);
        }
    }

    @Override
    public void setFeatureForUser(String featureName, Long userId, boolean enabled) {
        if (StringUtils.hasText(featureName) && userId != null) {
            userFeatures.computeIfAbsent(featureName, k -> new ConcurrentHashMap<>())
                       .put(userId, enabled);
            log.info("用户功能开关已设置: {} for user {} = {}", featureName, userId, enabled);
        }
    }

    @Override
    public void setFeatureForTenant(String featureName, Long tenantId, boolean enabled) {
        if (StringUtils.hasText(featureName) && tenantId != null) {
            tenantFeatures.computeIfAbsent(featureName, k -> new ConcurrentHashMap<>())
                          .put(tenantId, enabled);
            log.info("租户功能开关已设置: {} for tenant {} = {}", featureName, tenantId, enabled);
        }
    }

    @Override
    public void setFeatures(Map<String, Boolean> features) {
        if (features != null) {
            globalFeatures.putAll(features);
            log.info("批量设置功能开关: {}", features.size());
        }
    }

    @Override
    public Set<String> getEnabledFeatures() {
        return globalFeatures.entrySet().stream()
                .filter(Map.Entry::getValue)
                .map(Map.Entry::getKey)
                .collect(java.util.stream.Collectors.toSet());
    }

    @Override
    public Set<String> getEnabledFeatures(Long userId) {
        Set<String> enabled = new HashSet<>(getEnabledFeatures());
        
        if (userId != null) {
            // 添加用户特定的启用功能
            userFeatures.forEach((feature, userStates) -> {
                if (Boolean.TRUE.equals(userStates.get(userId))) {
                    enabled.add(feature);
                }
            });
        }
        
        return enabled;
    }

    @Override
    public Set<String> getEnabledFeaturesForTenant(Long tenantId) {
        Set<String> enabled = new HashSet<>(getEnabledFeatures());
        
        if (tenantId != null) {
            // 添加租户特定的启用功能
            tenantFeatures.forEach((feature, tenantStates) -> {
                if (Boolean.TRUE.equals(tenantStates.get(tenantId))) {
                    enabled.add(feature);
                }
            });
        }
        
        return enabled;
    }

    @Override
    public Map<String, Boolean> getAllFeatureStates() {
        return new HashMap<>(globalFeatures);
    }

    @Override
    public boolean featureExists(String featureName) {
        return globalFeatures.containsKey(featureName);
    }

    @Override
    public void addFeature(String featureName, boolean enabled) {
        if (StringUtils.hasText(featureName)) {
            globalFeatures.put(featureName, enabled);
            log.info("功能已添加: {} = {}", featureName, enabled);
        }
    }

    @Override
    public void removeFeature(String featureName) {
        if (StringUtils.hasText(featureName)) {
            globalFeatures.remove(featureName);
            userFeatures.remove(featureName);
            tenantFeatures.remove(featureName);
            featurePercentages.remove(featureName);
            featureWhitelists.remove(featureName);
            featureUsageStats.remove(featureName);
            log.info("功能已删除: {}", featureName);
        }
    }

    @Override
    public void setFeaturePercentage(String featureName, int percentage) {
        if (StringUtils.hasText(featureName) && percentage >= 0 && percentage <= 100) {
            featurePercentages.put(featureName, percentage);
            log.info("功能百分比已设置: {} = {}%", featureName, percentage);
        }
    }

    @Override
    public int getFeaturePercentage(String featureName) {
        return featurePercentages.getOrDefault(featureName, 0);
    }

    @Override
    public void addUserToWhitelist(String featureName, Long userId) {
        if (StringUtils.hasText(featureName) && userId != null) {
            featureWhitelists.computeIfAbsent(featureName, k -> ConcurrentHashMap.newKeySet())
                            .add(userId);
            log.info("用户已添加到白名单: {} for user {}", featureName, userId);
        }
    }

    @Override
    public void removeUserFromWhitelist(String featureName, Long userId) {
        if (StringUtils.hasText(featureName) && userId != null) {
            Set<Long> whitelist = featureWhitelists.get(featureName);
            if (whitelist != null) {
                whitelist.remove(userId);
                log.info("用户已从白名单移除: {} for user {}", featureName, userId);
            }
        }
    }

    @Override
    public boolean isUserInWhitelist(String featureName, Long userId) {
        if (!StringUtils.hasText(featureName) || userId == null) {
            return false;
        }
        
        Set<Long> whitelist = featureWhitelists.get(featureName);
        return whitelist != null && whitelist.contains(userId);
    }

    @Override
    public Set<Long> getWhitelistUsers(String featureName) {
        Set<Long> whitelist = featureWhitelists.get(featureName);
        return whitelist != null ? new HashSet<>(whitelist) : Collections.emptySet();
    }

    @Override
    public void refreshCache(String featureName) {
        // TODO: 从数据库重新加载功能开关配置
        log.info("功能开关缓存已刷新: {}", featureName != null ? featureName : "所有功能");
    }

    @Override
    public void clearCache() {
        globalFeatures.clear();
        userFeatures.clear();
        tenantFeatures.clear();
        featurePercentages.clear();
        featureWhitelists.clear();
        log.info("功能开关缓存已清空");
    }

    @Override
    public FeatureToggleStats getStats() {
        FeatureToggleStats stats = new FeatureToggleStats();
        stats.setTotalFeatures(globalFeatures.size());
        stats.setEnabledFeatures((int) globalFeatures.values().stream().mapToLong(b -> b ? 1 : 0).sum());
        stats.setDisabledFeatures(stats.getTotalFeatures() - stats.getEnabledFeatures());
        stats.setTotalChecks(totalChecks.get());
        stats.setCacheHits(cacheHits.get());
        stats.setCacheMisses(cacheMisses.get());
        
        Map<String, Long> usage = new HashMap<>();
        featureUsageStats.forEach((key, value) -> usage.put(key, value.get()));
        stats.setFeatureUsage(usage);
        
        return stats;
    }

    @Override
    public boolean checkByStrategy(String featureName, FeatureToggle.ToggleStrategy strategy, Map<String, Object> context) {
        switch (strategy) {
            case SIMPLE:
                return isEnabled(featureName);
            case USER_BASED:
                Long userId = extractUserId(context);
                return userId != null ? isEnabled(featureName, userId) : false;
            case TENANT_BASED:
                Long tenantId = extractTenantId(context);
                return tenantId != null ? isEnabledForTenant(featureName, tenantId) : false;
            case PERCENTAGE:
                userId = extractUserId(context);
                if (userId != null) {
                    Integer percentage = featurePercentages.get(featureName);
                    return percentage != null ? checkPercentageStrategy(featureName, userId, percentage) : false;
                }
                return false;
            case WHITELIST:
                userId = extractUserId(context);
                return userId != null ? isUserInWhitelist(featureName, userId) : false;
            default:
                return isEnabled(featureName);
        }
    }

    /**
     * 检查百分比策略
     */
    private boolean checkPercentageStrategy(String featureName, Long userId, int percentage) {
        if (percentage <= 0) {
            return false;
        }
        if (percentage >= 100) {
            return true;
        }
        
        // 使用一致性哈希确保同一用户的结果稳定
        String hashInput = featureName + ":" + userId;
        int hash = Math.abs(hashInput.hashCode()) % 100;
        return hash < percentage;
    }

    /**
     * 从上下文中提取用户ID
     */
    private Long extractUserId(Map<String, Object> context) {
        Object userId = context.get("userId");
        if (userId instanceof Long) {
            return (Long) userId;
        }
        if (userId instanceof Number) {
            return ((Number) userId).longValue();
        }
        if (userId instanceof String) {
            try {
                return Long.parseLong((String) userId);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * 从上下文中提取租户ID
     */
    private Long extractTenantId(Map<String, Object> context) {
        Object tenantId = context.get("tenantId");
        if (tenantId instanceof Long) {
            return (Long) tenantId;
        }
        if (tenantId instanceof Number) {
            return ((Number) tenantId).longValue();
        }
        if (tenantId instanceof String) {
            try {
                return Long.parseLong((String) tenantId);
            } catch (NumberFormatException e) {
                return null;
            }
        }
        return null;
    }

    /**
     * 更新功能使用统计
     */
    private void updateFeatureUsage(String featureName) {
        featureUsageStats.computeIfAbsent(featureName, k -> new AtomicLong(0))
                         .incrementAndGet();
    }
}
